package com.sailing.xjpb.ipaas.client.config;

import com.sailing.xjpb.common.exception.BusinessException;
import com.sailing.xjpb.ipaas.client.common.IpaasClientResponseErrorHandler;
import com.sailing.xjpb.ipaas.client.core.IpaasClientService;
import com.sailing.xjpb.ipaas.client.core.IpaasHttpClient;
import com.sailing.xjpb.ipaas.client.core.Sip3Service;
import com.sailing.xjpb.ipaas.client.core.UserContext;
import com.sailing.xjpb.ipaas.client.core.impl.IpaasClientServiceImpl;
import com.sailing.xjpb.ipaas.client.core.impl.Sip3ServiceImpl;
import com.sailing.xjpb.ipaas.client.core.repository.SipMenuRepository;
import com.sailing.xjpb.ipaas.client.core.repository.SipOrganizationRepository;
import com.sailing.xjpb.ipaas.client.core.repository.SipRoleRepository;
import com.sailing.xjpb.ipaas.client.core.repository.SipUserInfoRepository;
import com.sailing.xjpb.ipaas.client.translate.handler.IpaasOrgTranslateHandler;
import com.sailing.xjpb.ipaas.client.translate.handler.IpaasUserTranslateHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;

/**
 * ipaas client配置类
 *
 * @author YW
 */
@EnableConfigurationProperties(IpaasClientProperties.class)
@Configuration
public class IpaasClientAutoConfiguration {

    @Autowired
    private IpaasClientProperties ipaasClientProperties;

    @Bean("ipaasRestTemplate")
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
        restTemplate.setErrorHandler(new IpaasClientResponseErrorHandler());
        return restTemplate;
    }

    @Bean
    public IpaasClientService ipaasClientService(IpaasHttpClient ipaasHttpClient) {
        IpaasClientServiceImpl ipaasClientService = new IpaasClientServiceImpl();
        ipaasClientService.setIpaasHttpClient(ipaasHttpClient);
        return ipaasClientService;
    }

    @Bean
    IpaasHttpClient ipaasHttpClient() {
        return new IpaasHttpClient(restTemplate(), ipaasClientProperties);
    }

    @Bean
    public UserContext userContext() {
        return new UserContext();
    }

    /****ipaas用户和组织翻译器***/
    @Bean
    public IpaasOrgTranslateHandler ipaasOrgTranslateHandler() {
        return new IpaasOrgTranslateHandler();
    }

    @Bean
    public IpaasUserTranslateHandler ipaasUserTranslateHandler() {
        return new IpaasUserTranslateHandler();
    }

    /****ipaas接口bean初始化*****/
    @Bean
    public Sip3Service sip3Service() {
        return new Sip3ServiceImpl();
    }

    @Bean
    public SipOrganizationRepository sipOrganizationRepository() {
        return new SipOrganizationRepository();
    }

    @Bean
    public SipUserInfoRepository sipUserInfoRepository() {
        return new SipUserInfoRepository();
    }

    @Bean
    public SipMenuRepository sipMenuRepository() {
        return new SipMenuRepository();
    }

    @Bean
    public SipRoleRepository sipRoleRepository() {
        return new SipRoleRepository();
    }

    //@Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(xjpbCloseableHttpClient());
    }

    //@Bean("xjpbCloseableHttpClient")
    public CloseableHttpClient xjpbCloseableHttpClient() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(ipaasClientProperties.getConnectTimeout())
                .setConnectionRequestTimeout(ipaasClientProperties.getConnectionRequestTimeout())
                .setSocketTimeout(ipaasClientProperties.getSocketTimeout())
                .build();
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", trustSslFactory())
                .build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(ipaasClientProperties.getMaxTotal());
        connectionManager.setDefaultMaxPerRoute(ipaasClientProperties.getMaxPerRoute());
        return HttpClientBuilder.create()
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();
    }

    /**
     * 绕过验证
     */
    private static ConnectionSocketFactory trustSslFactory() {
        try {
            SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
            sslContextBuilder.loadTrustMaterial(TrustAllStrategy.INSTANCE);
            SSLContext sslContext = sslContextBuilder.build();
            return new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1.2"}, null,
                    NoopHostnameVerifier.INSTANCE);
        } catch (Exception e) {
            throw BusinessException.businessError("ipaas-SSLConnectionSocketFactory初始化出错！", e);
        }
    }
}

